<?php

namespace App\Services;

use App\Model;
use App\ModelProperty;
use App\ModelCategory;
use App\ModelClass;
use App\BaseDictionary;
use App\ModelClassProperty;
use App\ModelFilePart;
use App\UploadedFileState;
use App\Lib\Util\QueryPager;
use App\Lib\Util\LargeFileUploadHelper;
use Carbon\Carbon;
use DB;

class ModelService
{
    private function baseQuery()
    {
        return Model::select('id', 'name', 'description', 'main_image', 'broadcast_images', 'line_images', 'description', 'author_id', 'owner_id', 'class_id', 'sort_order', 'price', 'visit_count', 'vote_count');
    }

    public function getModels(Array $input, $paging = true)
    {
        $query = $this->baseQuery();

        if (isset($input['withProps']) && $input['withProps'] != '') {
            $query = $query->with('author', 'owner', 'modelClass', 'properties');
        } else {
            $query = $query->with('author', 'owner', 'modelClass');
        }

        if (!empty($input['categoryId'])) {
            $modelCategoryService = new ModelCategoryService();
            $allChildrenCategories = $modelCategoryService->getCascadeCategories(
                ModelCategory::select('id', 'name', 'parent_id')->where('id', $input['categoryId'])->first()->toArray()
            );
            $classIds = ModelClass::select('id')->whereIn('category_id', collect($allChildrenCategories)->pluck('id')->toArray())
                ->pluck('id')->toArray();

            if (empty($input['classId'])) {
                $query = $query->whereIn('class_id', $classIds);
            }
        }

        if (!empty($input['props'])) {
            $query = $query->whereHas('properties', function ($query) use ($input){
                $query->whereIn('value', explode(',', $input['props']));
            });
        }

        if (!empty($input['classId'])) {
            $query = $query->where('class_id', $input['classId']);
        }

        if (!empty($input['name'])) {
            $query->where('name', 'like', '%'.$input['name'].'%');
        }

        if (!empty($input['ownerId'])) {
            $query->where('owner_id', $input['ownerId']);
        }

        if (isset($input['ownerIds']) && $input['ownerIds'] != '') {
            $query->whereIn('owner_id', $input['ownerIds']);
        }

        if (isset($input['modelId']) && $input['modelId'] != '') {
            $query = $query->where('id', $input['modelId']);
        }

        $pager = new QueryPager($query);

        $pager->setRefectionMethodField('getFullImage');
        $pager->setRefectionMethodField('getFullImageThumb');
        $pager->setRefectionMethodField('classPath');
        $pager->setRefectionMethodField('getOwnerIconPath');
        $pager->setRefectionMethodField('getFullBroadCastImages');
        $pager->setRefectionMethodField('getFullLineImages');

        return $paging ? $pager->doPaginate($input, 'sort_order') :
            $pager->queryWithoutPaginate($input, 'sort_order');
    }

    public function getMainPageModels($queryType)
    {
        if ($queryType == 1) {
            return Model::select('id', 'name', 'description', 'main_image', 'author_id', 'owner_id', 'class_id')->where('is_new', BaseDictionary::$KEY_YES)
                ->orderBy('is_new_order')->skip(0)->take(8)->get();
        } else if ($queryType == 2) {
            return Model::select('id', 'name', 'description', 'main_image', 'author_id', 'owner_id', 'class_id')->where('is_recommand', BaseDictionary::$KEY_YES)
                ->orderBy('is_recommand_order')->skip(0)->take(8)->get();
        } else if ($queryType == 3) {
            return Model::select('id', 'name', 'description', 'main_image', 'author_id', 'owner_id', 'class_id')->where('is_recommand_materials', BaseDictionary::$KEY_YES)
                ->orderBy('is_recommand_materials_order')->skip(0)->take(8)->get();
        }

        return null;
    }

    public function saveNewModel(Array $input, $authorId, $ownerId)
    {
        DB::transaction(function () use ($input, $authorId, $ownerId) {
            $largeFileUploadHelper = new LargeFileUploadHelper();
            
            $uploadFileResult = $largeFileUploadHelper->doMergeThunkFile($input['modelGuid']);
            $largeFileUploadHelper->releaseSpace($input['modelGuid']);

            if ($uploadFileResult['result']) {
                $model = Model::create([
                    'name' => $input['name'],
                    'description' => $input['name'],
                    'main_image' => $input['main_image'],
                    'class_id' => $input['class_id'],
                    'price' => $input['price'],
                    'author_id' => $authorId,
                    'owner_id' => $ownerId,
                    'file_guid' => $input['modelGuid'],
                    'file_name' => $uploadFileResult['fileOriginName'],
                    'md5_name' => $uploadFileResult['md5'],
                    'upload_date' => Carbon::now()
                ]);

                $thumbImages = explode(',', $input['fileThumbs']);
                $thumnImageKey = $input['fileThumbGuid'];
                $processedThumbImages = '';

                foreach ($thumbImages as $thumbImage) {
                    $file = UploadedFileState::select('file_id as id')->where('state', 0)->where('batch_upload_origin_name', $thumbImage)
                        ->where('guid', $thumnImageKey)->first();
    
                    if (isset($file)) {
                        $processedThumbImages .= $file->id.',';
                        UploadedFileState::where('state', 0)->where('batch_upload_origin_name', $thumbImage)->where('guid', $thumnImageKey)
                            ->update([
                                'batch_upload_origin_name' => null,
                                'guid' => null,
                                'state' => 1
                            ]);
                    }
                }

                if ($processedThumbImages != '') {
                    $processedThumbImages = substr($processedThumbImages, 0, strlen($processedThumbImages) - 1);
                } else {
                    $processedThumbImages = $input['main_image'];
                }

                $lineImages = explode(',', $input['fileLines']);
                $lineImageKey = $input['fileLineGuid'];
                $processedLineImages = '';

                foreach ($lineImages as $lineImage) {
                    $file = UploadedFileState::select('file_id as id')->where('state', 0)->where('batch_upload_origin_name', $lineImage)
                        ->where('guid', $lineImageKey)->first();
    
                    if (isset($file)) {
                        $processedLineImages .= $file->id.',';
                        UploadedFileState::where('state', 0)->where('batch_upload_origin_name', $lineImage)->where('guid', $lineImageKey)
                            ->update([
                                'batch_upload_origin_name' => null,
                                'guid' => null,
                                'state' => 1
                            ]);
                    }
                }

                if ($processedLineImages != '') {
                    $processedLineImages = substr($processedLineImages, 0, strlen($processedLineImages) - 1);
                }

                $thunkFiles = $uploadFileResult['fileIds'];

                $thunkFileCount = count($thunkFiles);

                for ($i=0; $i<$thunkFileCount; $i++) {
                    ModelFilePart::create([
                        'model_id' => $model->id, 
                        'trunk_id' => $thunkFiles[$i]['fileKey'],
                        'sort_order' => $i,
                        'file_id' => $thunkFiles[$i]['fileName']
                    ]);
                }

                $props = json_decode($input['props'], true);

                $seq = 0;

                $propDesc = '';

                foreach($props as $propGroup) {
                    foreach($propGroup as $propItem) {
                        ModelProperty::create([
                            'model_id' => $model->id, 
                            'sequence' => $seq,
                            'sort_order' => $seq,
                            'name' => $propItem['name'],
                            'value' => $propItem['id']
                        ]);

                        $propDesc .= $propItem['id'].',';
                        $seq++;
                    }
                }

                if ($propDesc != '') {
                    $propDesc = substr($propDesc, 0, strlen($propDesc) - 1);
                }

                $model->broadcast_images = $processedThumbImages;
                $model->description = $propDesc;
                $model->line_images = $processedLineImages;
                $model->save();
            }
        });
    }

    public function delete($modelId)
    {
        DB::transaction(function () use ($modelId) {
            $model = Model::findOrFail($modelId);

            ModelFilePart::where('model_id', $model->id)->delete();

            ModelProperty::where('model_id', $model->id)->delete();

            $model->delete();
        });
    }

    public function hasConstrait($modelId)
    {
        return ModelFilePart::where('model_id', $modelId)->count() > 0 || ModelProperty::where('model_id', $modelId)->count() > 0;
    }

    public function downloadModel($modelId)
    {
        $files = ModelFilePart::where('model_id', $modelId)->orderBy('sort_order')->get();

        $c = count($files);

        for ($i=0; $i<$c; $i++) {
            $file = $files[$i];
        }
    }
}
